package com.ksyun.campus.client;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ksyun.campus.client.domain.Result;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;
import java.io.OutputStream;

public class FSOutputStream extends OutputStream {

    private final HttpClient httpClient;
    private final String filePath;
    private final String fileSystemName;
    private static final int CHUNK_SIZE = 1024 * 1024 * 10; // 10MB

    public FSOutputStream(HttpClient httpClient, String filePath, String fileSystemName) {
        this.httpClient = httpClient;
        this.filePath = filePath;
        this.fileSystemName = fileSystemName;
    }

    @Override
    public void write(int b) throws IOException {
        // 将单个字节写入 byte[] 数组，然后调用 write(byte[] b)
        write(new byte[]{(byte) b});
    }

    @Override
    public void write(byte[] b) throws IOException {
        // 判断数据大小是否小于 CHUNK_SIZE
        if (b.length <= CHUNK_SIZE) {
            writeChunk(b, 0, b.length);
        } else {
            // 分片写入
            int offset = 0;
            while (offset < b.length) {
                int bytesToWrite = Math.min(CHUNK_SIZE, b.length - offset);
                writeChunk(b, offset, bytesToWrite);
                offset += bytesToWrite;
            }
        }
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        // 判断数据大小是否小于 CHUNK_SIZE
        if (len <= CHUNK_SIZE) {
            writeChunk(b, off, len);
        } else {
            // 分片写入
            int offset = off;
            while (offset < off + len) {
                int bytesToWrite = Math.min(CHUNK_SIZE, len - (offset - off));
                writeChunk(b, offset, bytesToWrite);
                offset += bytesToWrite;
            }
        }
    }

    private void writeChunk(byte[] b, int offset, int length) throws IOException {
        String url = "http://localhost:9000/write"; // 实际的服务器地址
        HttpPost httpPost = new HttpPost(url);

        // 将 fileSystemName 添加到请求头
        httpPost.setHeader("fileSystemName", fileSystemName);

        // 创建一个 MultipartEntityBuilder 来构建请求内容
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();

        // 添加要写入的分片数据到请求内容中
        byte[] chunkData = new byte[length];
        System.arraycopy(b, offset, chunkData, 0, length);
        builder.addBinaryBody("fileContent", chunkData, ContentType.DEFAULT_BINARY, "defaultFileName");

        builder.addTextBody("path", filePath);
        builder.addTextBody("offset", String.valueOf(offset));
        builder.addTextBody("length", String.valueOf(length));

        // 将请求实体设置到 HttpPost 中
        httpPost.setEntity(builder.build());

        // 发送请求并处理响应
        try (CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost)) {

            String jsonResponse = EntityUtils.toString(response.getEntity());
            ObjectMapper objectMapper = new ObjectMapper();
            Result result = objectMapper.readValue(jsonResponse, Result.class);

//            int statusCode = response.getCode();
//            String responseBody;
//            try {
//                responseBody = EntityUtils.toString(response.getEntity());
//            } catch (ParseException e) {
//                throw new RuntimeException(e);
//            }

            if (result.getCode().equals("200")) {
                System.out.println("Chunk written successfully: " +filePath);
            } else {
                System.out.println("Failed to write chunk: " + filePath);
                throw new IOException("Failed to write chunk: " + filePath);
            }

        }catch (Exception e){
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void close() throws IOException {
        // 可以在这里关闭流资源，或者其他清理操作
        super.close();
    }
}
